from datetime import datetime
from application.celery import app
from django.db import transaction
from apps.tms.job.initialize import Initialize
from apps.tms.models import Job, JobExecution, JobLog, TestCase
from .results import *


@app.task(ignore_result=True)
def init_execution(job_id: str, job_execution_id=None, testcases=None):
    """初始化任务执行记录"""
    job = Job.objects.filter(id=job_id).first()
    job_execution, created = JobExecution.objects.get_or_create(
        id=job_execution_id,
        defaults={
            "name": job.name,
            "job_id": job_id,
            "run_time": datetime.now(),
            "status": Status.RUNNING.value,
            "dept_belong_id": job.dept_belong_id,
        },
    )
    testcases = testcases if testcases else job.tcs.all()
    for testcase in testcases:
        init_execution_case(job, job_execution.id, testcase)
    return job_execution


@app.task(ignore_result=True)
def init_execution_case(job: Job, job_execution_id: str, testcase: TestCase):
    joblog_data = [
        {
            "testcase_id": testcase.id,
            "job_id": job.id,
            "job_execution_id": job_execution_id,
            "product": testcase.product,
            "module": testcase.module,
            "number": testcase.number,
            "name": testcase.name,
            "level": testcase.level,
            "type": testcase.type,
            "stage": testcase.stage,
            "isauto": testcase.isauto,
            "precondition": testcase.precondition,
            "steps": testcase.steps,
            "script": testcase.script,
            "creator": testcase.creator,
            "dept_belong_id": testcase.dept_belong_id,
        }
    ]
    Initialize().save(JobLog, joblog_data)


@app.task(ignore_result=True)
def update_job(job_id: str, **kwargs):
    """更新任务"""
    return Job.objects.filter(id=job_id).update(**kwargs)


@app.task(ignore_result=True)
def update_execution(job_execution_id: str, **kwargs):
    """更新任务执行记录"""
    JobExecution.objects.filter(id=job_execution_id).update(**kwargs)


@app.task(ignore_result=True)
def update_execution_case(joblog_id, **kwargs):
    """更新任务执行用例"""
    JobLog.objects.filter(id=joblog_id).update(**kwargs)


@app.task(ignore_result=True)
def update_execution_step(joblog_id, step):
    """更新任务执行用例"""
    try:
        # 使用事务确保数据一致性
        with transaction.atomic():
            job_log = JobLog.objects.select_for_update().filter(id=joblog_id).first()
            if job_log:
                steps = job_log.steps
                index = step.get("id", None)
                if index:
                    # 确定索引有效且在列表长度内
                    if index <= len(steps):
                        steps[index - 1] = step
                        job_log.steps = steps
                        job_log.save()  # 更新记录
                    else:
                        print(f"Index {index} out of range for joblog {joblog_id}")
                else:
                    print(f"step id is None '{step}'")
            else:
                print(f"No joblog found with id {joblog_id}")

    except Exception as e:
        print(f"Error updating execution step: {e}")


@app.task(ignore_result=True)
def update_joblog_status_from_result(joblog_id):
    """根据结果计数确定最终状态并更新测试用例"""
    try:
        # 使用事务确保数据一致性
        with transaction.atomic():
            analysis = None
            pass_count, fail_count, block_count = 0, 0, 0
            job_log = JobLog.objects.select_for_update().filter(id=joblog_id).first()
            if job_log:
                for step in job_log.steps:
                    result = step.get("result")
                    pass_count += result == Result.PASS.value
                    fail_count += result == Result.FAIL.value
                    block_count += result == Result.BLOCK.value
                if fail_count + block_count == 0:
                    status = Status.SUCCESS.value
                else:
                    analysis = "0"
                    if block_count > 0:
                        status = Status.BLOCK.value
                    else:
                        status = Status.FAILED.value
                job_log.status = status
                job_log.finished = datetime.now()
                job_log.analysis = analysis
                job_log.save()
            else:
                print(f"No joblog found with id {joblog_id}")

    except Exception as e:
        print(f"Error updating joblog status from results: {e}")


@app.task(ignore_result=True)
def get_testcase_object(joblog_id, sync_case):
    """根据sync_case标志检索正确的TestCase对象"""
    testcase_log = JobLog.objects.filter(id=joblog_id).first()
    return (
        TestCase.objects.filter(id=testcase_log.testcase.id).first()
        if sync_case
        else testcase_log
    )


@app.task(ignore_result=True)
def finalize_execution(job_id, job_execution_id):
    update_job(job_id, status=Status.SUCCESS.value, finished=datetime.now())
    update_execution(
        job_execution_id, status=Status.SUCCESS.value, finished=datetime.now()
    )
